package com.zhongwang.mms.module.buy.controller;

import com.alibaba.excel.EasyExcel;
import com.zhongwang.mms.base.BaseController;
import com.zhongwang.mms.common.JsonResult;
import com.zhongwang.mms.gen.entity.User;
import com.zhongwang.mms.module.basic.dao.DictCommonDao;
import com.zhongwang.mms.module.basic.model.DictCommon;
import com.zhongwang.mms.module.buy.dao.BPreOrderPlanDao;
import com.zhongwang.mms.module.buy.model.*;
import com.zhongwang.mms.module.buy.service.BuyProcurementPlanService;
import com.zhongwang.mms.module.system.log.LogService;
import com.zhongwang.mms.util.FileUtils;
import com.zhongwang.mms.util.ShiroUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.util.UriUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
 * 采购计划编辑接口层
 */
@SuppressWarnings("ALL")
@RequestMapping("/buy/procurementPlan")
@Controller
public class BuyProcurementPlanController extends BaseController {
    @Autowired
    private BPreOrderPlanDao bPreOrderPlanDao;
    @Autowired
    private BuyProcurementPlanService buyProcurementPlanService;
    @Autowired
    private LogService logService;
    @Autowired
    private DictCommonDao dictCommonDao;
    /**
     * 上传文件路径
     */
    @Value("${user.upload.path}")
    private String uploadPath;

    /**
     * 跳转到预购计划审核页面
     *
     * @param model
     * @return
     */
    @GetMapping("/page")
    public String page(Model model) {
        List<DictCommon> dictCommonList = dictCommonDao.findDictByGroupName("票据类型");
        model.addAttribute("dictCommonList", dictCommonList);
        return "/buy/preOrderPlan/purchase/page";
    }

    /**
     * 查询采购计划列表 -- 明细模式 - 普通搜索
     *
     * @param where 搜索条件
     * @return 采购计划列表
     */
    @ResponseBody
    @RequestMapping("/list")
    @RequiresPermissions(value = {"buy:procurementplan:view"}, logical = Logical.OR)
    public JsonResult list(BPreOrderPlan where) {
        startPage();
        where.setAssignPurchaserId(ShiroUtils.getUserId());
        List<BPreOrderPlan> list = buyProcurementPlanService.findProcurementPlanByQuery(where);
        return jsonResult(list);
    }
    /**
     * 查询采购计划列表 -- 明细模式 - 高级搜索
     *
     * @param where 搜索条件
     * @return 采购计划列表
     */
    @ResponseBody
    @RequestMapping("/advanceList")
    @RequiresPermissions(value = {"buy:procurementplan:view"}, logical = Logical.OR)
    public JsonResult advanceList(BPreOrderPlan where) {
        startPage();
        where.setAssignPurchaserId(ShiroUtils.getUserId());
        List<BPreOrderPlan> list = buyProcurementPlanService.findProcurementPlanByQueryForAdvanceList(where);
        return jsonResult(list);
    }

    /**
     * 查询采购计划列表 -- 汇总模式
     * @param where 搜索条件
     * @return 采购计划列表
     */
    @ResponseBody
    @RequestMapping("/summaryList")
    @RequiresPermissions(value = {"buy:procurementplan:view"}, logical = Logical.OR)
    public JsonResult summaryList(BPreOrderPlan where) {
        startPage();
        where.setAssignPurchaserId(ShiroUtils.getUserId());
        List<BPreOrderPlan> list = buyProcurementPlanService.findProcurementSummaryListPlanByQuery(where);
        return jsonResult(list);
    }



    /**
     * 导出 Excel
     * @param where 搜索条件
     * @param response 下载使用
     * @return 下载文件流
     */
    @PostMapping("/exportExcel")
    @RequiresPermissions(value = {"buy:procurementplan:edit"}, logical = Logical.OR)
    @ResponseBody
    public ResponseEntity<byte[]> exportExcel(BPreOrderPlan where,HttpServletResponse response) throws IOException {
        //获取当前登录用户
        User user = ShiroUtils.getUser();
        where.setAssignPurchaserId(ShiroUtils.getUserId());
        //获取当前登录用户可以导出的Excel的列表数据
        List<BPreOrderPlan> list = bPreOrderPlanDao.selectProcurementPlanByWhere(where);
        //拼装成导出Excel所需要的列表
        List<ProcurementPlanExportImportModel> exportModels = new ArrayList<>();
        for (BPreOrderPlan preOrderPlan : list) {
            if(preOrderPlan.getReceiptStatus().intValue() == 1) {
                ProcurementPlanExportImportModel procurementPlanExportImportModel = new ProcurementPlanExportImportModel();
                procurementPlanExportImportModel.setTrackNumber(preOrderPlan.getTrackNumber());
                procurementPlanExportImportModel.setMaterialDesc(preOrderPlan.getMaterialDesc());
                procurementPlanExportImportModel.setProCode(preOrderPlan.getProCode());
                procurementPlanExportImportModel.setProName(preOrderPlan.getProName());
                procurementPlanExportImportModel.setNum(preOrderPlan.getNum());
                procurementPlanExportImportModel.setUnit(preOrderPlan.getUnit());
                procurementPlanExportImportModel.setPcNo(preOrderPlan.getPcNo());
                procurementPlanExportImportModel.setPurchNum(preOrderPlan.getNum());
                procurementPlanExportImportModel.setPurchUnit(preOrderPlan.getPurchUnit());
                procurementPlanExportImportModel.setTaxRate(preOrderPlan.getTaxRate());
                procurementPlanExportImportModel.setBillType(preOrderPlan.getBillType());
                procurementPlanExportImportModel.setUnitPrice(preOrderPlan.getUnitPrice());
                procurementPlanExportImportModel.setTotalPrice(preOrderPlan.getTotalPrice());
                procurementPlanExportImportModel.setSupplier(preOrderPlan.getSupplier());
                procurementPlanExportImportModel.setPurchRemark(preOrderPlan.getPurchRemark());
                exportModels.add(procurementPlanExportImportModel);
                preOrderPlan.setExportRecord(user.getName()+" 已导出");
                //更新导出记录到数据库
                bPreOrderPlanDao.updateExportRecordByPrimaryKey(preOrderPlan);
            }
        }
        //获取票据类型列表
        List<DictCommon> dictCommonList = dictCommonDao.findDictByGroupName("票据类型");
        //导出Excel所需的String类型列表
        List<String> billTypeList = new ArrayList<>();
        //拼装导出Excel所需的String类型列表
        for (DictCommon dc : dictCommonList) {
            billTypeList.add(dc.getName());
        }
        //创建内存
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        //采用EasyExcel将数据写入到内存中
        EasyExcel.write(bos, ProcurementPlanExportImportModel.class)
                .registerWriteHandler(new RedHeadStyleHandler(ProcurementPlanExportImportModel.class))         // 9 列红色背景 处理器
                .registerWriteHandler(new InvoiceTypeDropdownHandler(billTypeList, 5000)) // 下拉框 处理器
                .sheet("sheet1")//sheet名字
                .doWrite(exportModels);//开始写入
        String fileName =  URLEncoder.encode("采购计划编辑", "UTF-8").replace("+", "%20");
        //记录操作日志
        logService.saveLog("采购计划编辑——导出", "执行导出操作，导出"+exportModels.size()+"行数据！");
        return ResponseEntity.ok()
                .contentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"))
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename*=utf-8''" + fileName + ".xlsx")
                .body(bos.toByteArray());
    }/**
     * 导出 Excel - 高级搜索
     * @param where 搜索条件
     * @param response 下载使用
     * @return 下载文件流
     */
    @PostMapping("/exportExcelForAdvanced")
    @RequiresPermissions(value = {"buy:procurementplan:edit"}, logical = Logical.OR)
    @ResponseBody
    public ResponseEntity<byte[]> exportExcelForAdvanced(BPreOrderPlan where,HttpServletResponse response) throws IOException {
        //获取当前登录用户
        User user = ShiroUtils.getUser();
        where.setAssignPurchaserId(ShiroUtils.getUserId());
        //获取当前登录用户可以导出的Excel的列表数据
        List<BPreOrderPlan> list = bPreOrderPlanDao.findProcurementPlanByQueryForAdvanceList(where);
        //拼装成导出Excel所需要的列表
        List<ProcurementPlanExportImportModel> exportModels = new ArrayList<>();
        for (BPreOrderPlan preOrderPlan : list) {
            if(preOrderPlan.getReceiptStatus().intValue() == 1) {
                ProcurementPlanExportImportModel procurementPlanExportImportModel = new ProcurementPlanExportImportModel();
                procurementPlanExportImportModel.setTrackNumber(preOrderPlan.getTrackNumber());
                procurementPlanExportImportModel.setMaterialDesc(preOrderPlan.getMaterialDesc());
                procurementPlanExportImportModel.setProCode(preOrderPlan.getProCode());
                procurementPlanExportImportModel.setProName(preOrderPlan.getProName());
                procurementPlanExportImportModel.setNum(preOrderPlan.getNum());
                procurementPlanExportImportModel.setUnit(preOrderPlan.getUnit());
                procurementPlanExportImportModel.setPcNo(preOrderPlan.getPcNo());
                procurementPlanExportImportModel.setPurchNum(preOrderPlan.getNum());
                procurementPlanExportImportModel.setPurchUnit(preOrderPlan.getPurchUnit());
                procurementPlanExportImportModel.setTaxRate(preOrderPlan.getTaxRate());
                procurementPlanExportImportModel.setBillType(preOrderPlan.getBillType());
                procurementPlanExportImportModel.setUnitPrice(preOrderPlan.getUnitPrice());
                procurementPlanExportImportModel.setTotalPrice(preOrderPlan.getTotalPrice());
                procurementPlanExportImportModel.setSupplier(preOrderPlan.getSupplier());
                procurementPlanExportImportModel.setPurchRemark(preOrderPlan.getPurchRemark());
                exportModels.add(procurementPlanExportImportModel);
                preOrderPlan.setExportRecord(user.getName() + " 已导出");
                //更新导出记录到数据库
                bPreOrderPlanDao.updateExportRecordByPrimaryKey(preOrderPlan);
            }
        }
        //获取票据类型列表
        List<DictCommon> dictCommonList = dictCommonDao.findDictByGroupName("票据类型");
        //导出Excel所需的String类型列表
        List<String> billTypeList = new ArrayList<>();
        //拼装导出Excel所需的String类型列表
        for (DictCommon dc : dictCommonList) {
            billTypeList.add(dc.getName());
        }
        //创建内存
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        //采用EasyExcel将数据写入到内存中
        EasyExcel.write(bos, ProcurementPlanExportImportModel.class)
                .registerWriteHandler(new RedHeadStyleHandler(ProcurementPlanExportImportModel.class))         // 9 列红色背景 处理器
                .registerWriteHandler(new InvoiceTypeDropdownHandler(billTypeList, 5000)) // 下拉框 处理器
                .sheet("sheet1")//sheet名字
                .doWrite(exportModels);//开始写入
        String fileName =  URLEncoder.encode("采购计划编辑", "UTF-8").replace("+", "%20");
        //记录操作日志
        logService.saveLog("采购计划编辑——导出", "执行导出操作，导出"+exportModels.size()+"行数据！");
        return ResponseEntity.ok()
                .contentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"))
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename*=utf-8''" + fileName + ".xlsx")
                .body(bos.toByteArray());
    }
    /**
     * 根据预购编号code查询预购计划列表
     * @param code 预购编号
     * @return 预购计划列表
     */
    @ResponseBody
    @PostMapping("/getProOrderPlanListByCode")
    @RequiresPermissions(value = {"buy:procurementplan:view"}, logical = Logical.OR)
    public JsonResult getProOrderPlanListByCode(String code) {
        List<BPreOrderPlan> list = buyProcurementPlanService.findBPreOrderPlanByCode(code);
        return success().setData(list);
    }

    /**
     * 根据预购计划ID判断附件文件是否存在
     * @param id
     * @return
     */
    @ResponseBody
    @PostMapping("/getAttachmentIsExist")
    @RequiresPermissions(value = {"buy:procurementplan:download"}, logical = Logical.OR)
    public JsonResult getAttachmentIsExist(Integer id) {
        BPreOrderPlan preOrderPlan = buyProcurementPlanService.getBPreOrderPlanByPrimaryKey(id);
        String attachmentUrl = preOrderPlan.getAttachment();
        String msg = "有文件";
        if(attachmentUrl == null || attachmentUrl.equals("")){
            msg = "没有文件";
        }else{
            attachmentUrl = attachmentUrl.replace("/files/", "/");
            String localPath = uploadPath + attachmentUrl.substring(attachmentUrl.indexOf("/"));
            if(new File(localPath).exists()) {
                return success(msg);
            }
        }
        return error(msg);
    }

    /**
     * 根据预购计划ID下载附件
     * @param id 预购计划ID
     */
    @GetMapping("/downloadAttachment/{id}")
    @RequiresPermissions(value = {"buy:procurementplan:download"}, logical = Logical.OR)
    public ResponseEntity<Resource> downloadAttachment(@PathVariable("id") Integer id,
                                                       HttpServletResponse httpServletResponse,
                                                       HttpServletRequest request) throws MalformedURLException {
        BPreOrderPlan preOrderPlan = buyProcurementPlanService.getBPreOrderPlanByPrimaryKey(id);
        String attachmentUrl = preOrderPlan.getAttachment();
        attachmentUrl = attachmentUrl.replace("/files/", "/");
        String localPath = uploadPath + attachmentUrl.substring(attachmentUrl.indexOf("/"));
        Path realPath = Paths.get(localPath); // 真实文件
        Resource resource = new UrlResource(realPath.toUri());
        if (!resource.exists()) {
            return ResponseEntity.notFound().build();
        }else{
            // 根据浏览器类型决定编码方式
            String agent = request.getHeader("User-Agent");
            String disposition = "attachment; filename*=UTF-8''" + UriUtils.encode(preOrderPlan.getAttachmentName(), StandardCharsets.UTF_8);
            logService.saveLog("采购管理-采购计划编辑", "下载预购主题为：" + preOrderPlan.getName() + "，预购编码为：" + preOrderPlan.getCode() + ",物料跟踪码为：" + preOrderPlan.getTrackNumber() + ",物料描述为：" + preOrderPlan.getMaterialDesc() + "的名称为：" + preOrderPlan.getAttachmentName() + "的附件（附件大小：" + FileUtils.formatFileSize(realPath.toFile().length()) + "）！");
            return ResponseEntity.ok()
                    .contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .header(HttpHeaders.CONTENT_DISPOSITION, disposition)
                    .body(resource);
        }
    }

    /**
     * 驳回计划
     * @param codes 驳回的预购编号
     * @param rejectReason 驳回原因
     * */
    @ResponseBody
    @PostMapping("/reject")
    @RequiresPermissions({"buy:procurementplan:edit"})
    public JsonResult reject(@RequestParam("codes") List<String> codes,String rejectReason) {
        return jsonResult(buyProcurementPlanService.reject(codes,rejectReason));
    }

    /**
     * 导入-保存采购计划单
     */
    @ResponseBody
    @PostMapping("/importExcel")
    @RequiresPermissions(value = {"buy:procurementplan:edit"}, logical = Logical.OR)
    public JsonResult importExcel(@ModelAttribute ProcurementPlanImportModel data) {
        if(data.getRows().size() > 0){
            //拆解模型，拼装成可以存储进数据库的模型
            List<BPreOrderPlan> bPreOrderPlanList = new ArrayList();
            User user = (User) SecurityUtils.getSubject().getPrincipal();
            for (int i = 0; i < data.getRows().size(); i++) {
                ProcurementPlanExportImportModel ppeim = data.getRows().get(i);
                BPreOrderPlan bPreOrderPlan = new BPreOrderPlan();
                bPreOrderPlan.setTrackNumber(ppeim.getTrackNumber());
                bPreOrderPlan.setPcNo(ppeim.getPcNo());
                bPreOrderPlan.setPurchNum(ppeim.getPurchNum());
                bPreOrderPlan.setPurchUnit(ppeim.getPurchUnit());
                bPreOrderPlan.setTaxRate(ppeim.getTaxRate());
                bPreOrderPlan.setBillType(ppeim.getBillType());
                bPreOrderPlan.setUnitPrice(ppeim.getUnitPrice());
                bPreOrderPlan.setTotalPrice(ppeim.getTotalPrice());
                bPreOrderPlan.setSupplier(ppeim.getSupplier());
                bPreOrderPlan.setPurchCreate(new Date());
                bPreOrderPlan.setPurchRemark(ppeim.getPurchRemark());
                bPreOrderPlanList.add(bPreOrderPlan);
            }
            Integer res = buyProcurementPlanService.saveImportProcurementPlan(bPreOrderPlanList);
            if (res > 0) {
                logService.saveLog("采购管理-采购计划编辑","导入采购计划数据数共"+data.getRows().size()+"条数据！");
                return JsonResult.success("保存成功！");
            }else{
                return JsonResult.fail("保存失败，请通知管理员！");
            }
        }else{
            return JsonResult.fail("保存失败，请导入或填写预购清单！");
        }
    }

    /**
     * 根据跟踪号修改收货状态
     * @param trackNumbers 物料跟踪号集合
     * @param receiptStatus 收缩状态值
     * @return 操作结果
     */
    @ResponseBody
    @PostMapping("/changeReceiptStatusByTrackNumber")
    @RequiresPermissions(value = {"buy:procurementplan:edit"}, logical = Logical.OR)
    public JsonResult changeReceiptStatusByTrackNumber(@RequestParam("trackNumbers") List<String> trackNumbers,Integer receiptStatus) {
        Integer res = buyProcurementPlanService.changeReceiptStatusByTrackNumber(trackNumbers,receiptStatus);
        if (res > 0) {
            return success();
        }
        return error("操作失败！");
    }
    /**
     * 根据物料跟踪号集合撤销采购
     * @param trackNumbers 物料跟踪号集合
     * @return 操作结果
     */
    @ResponseBody
    @PostMapping("/revocationProcurementByTrackNumber")
    @RequiresPermissions(value = {"buy:procurementplan:edit"}, logical = Logical.OR)
    public JsonResult revocationProcurementByTrackNumber(@RequestParam("trackNumbers") List<String> trackNumbers) {
        Integer res = buyProcurementPlanService.revocationProcurementByTrackNumber(trackNumbers);
        if (res > 0) {
            return success();
        }
        return error("操作失败！");
    }

    /**
     * 获取票据类型列表
     * @return
     */
    @ResponseBody
    @PostMapping("/getBillTypeList")
    @RequiresPermissions(value = {"buy:procurementplan:view"}, logical = Logical.OR)
    public JsonResult getBillTypeList() {
        Integer res = 0;
        //获取票据类型列表
        List<DictCommon> dictCommonList = dictCommonDao.findDictByGroupName("票据类型");
        res = dictCommonList.size();
        if (res > 0) {
            return success().setData(dictCommonList);
        }
        return error("操作失败！");
    }

    /**
     * 获取修改所使用的回显数据
     * @param where
     * @return
     */
    @ResponseBody
    @PostMapping("/getBPreOrderPlanAllInfoByTrackNumber")
    @RequiresPermissions(value = {"buy:procurementplan:view","buy:procurementplan:edit"}, logical = Logical.OR)
    public JsonResult getBPreOrderPlanAllInfoByTrackNumber(BPreOrderPlan where) {
        Integer res = 0;
        BPreOrderPlan bPreOrderPlan = buyProcurementPlanService.getProcurementPlanByQueryAndTrackNumber(where);
        if (bPreOrderPlan != null) {
            return success().setData(bPreOrderPlan);
        }
        return error("操作失败！");
    }

    /**
     * 根据物料跟踪号保存修改的外购计划数据
     * @param data 物料跟踪号和修改的外购计划数据
     * @return 保存结果
     */
    @ResponseBody
    @PostMapping("/saveUpdate")
    @RequiresPermissions(value = {"buy:procurementplan:edit"}, logical = Logical.OR)
    public JsonResult saveUpdate(BPreOrderPlan data) {
        Integer res = buyProcurementPlanService.saveUpdate(data);
        if (res>0) {
            return success("保存成功！");
        }
        return error("保存失败！");
    }
    /**
     * 根据物料跟踪号保存修改的外购计划数据的收货数量
     * @param data 物料跟踪号和修改的外购计划数据的收货数量
     * @return 保存结果
     */
    @ResponseBody
    @PostMapping("/updateFormReceivedNum")
    @RequiresPermissions(value = {"buy:procurementplan:edit"}, logical = Logical.OR)
    public JsonResult updateFormReceivedNum(BPreOrderPlan data) {
        Integer res = buyProcurementPlanService.saveReceivedNum(data);
        if (res>0) {
            return success("保存成功！");
        }
        return error("保存失败！");
    }

    /**
     * 根据物料跟踪号获取物料跟踪号是空的采购计划数量
     * @param trackNumbers 物料跟踪号几号
     * @return 跟踪号是空的采购计划数量
     */
    @ResponseBody
    @PostMapping("/getPcNoNullCountByTrackNumber")
    @RequiresPermissions(value = {"buy:procurementplan:edit"}, logical = Logical.OR)
    public JsonResult getPcNoNullCountByTrackNumber(@RequestParam("trackNumbers") List<String> trackNumbers) {
        Integer res = buyProcurementPlanService.getPcNoNullCountByTrackNumber(trackNumbers);
        return success().setData(res);
    }
}
